﻿#region copyright
//<copyright>
// Copyright(C) 2012 TrackerRealm Corporation
// This file is part of the open source project - Jazz. http://jazz.codeplex.com
// 
// Jazz is open software: you can redistribute it and/or modify it 
// under the terms of the GNU Affero General Public License (AGPL) as published by 
// the Free Software Foundation, version 3 of the License.
// 
// Jazz is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty 
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
//  See the GNU Affero General Public License (AGPL) for more details.
// 
// You should have received a copy of the GNU General Public 
// License along with Jazz.  If not, see <http://www.gnu.org/licenses/>.
//
// REMOVAL OF THIS NOTICE IS VIOLATION OF THE COPYRIGHT. 
//</copyright>
#endregion
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TrackerRealm.Jazz.Client;
using TrackerRealm.Jazz.Common;
using PostSharp.Extensibility;
using TrackerRealm.Jazz.Json;
using TrackerRealm.Jazz.JsonSpecialized;
using KellermanSoftware.CompareNetObjects;
using System.Runtime.Serialization;
using TrackerRealm.Jazz.Client.Custom;

namespace JazzClientTest
{
    /// <summary>
    /// This demonstrate setting an ACL of a Jazz object.
    /// 
    /// For more information on states see - http://wiki.jazzfire.net/ACL.ashx
    /// </summary>
    [TestClass]
    public class ACLTests
    {

        #region AclWorkspaceTest
        /// <summary>
        /// Demonstrates how to create a workspace that is only accessible given
        /// that the logged in user has a roled named "Manager".
        /// </summary>
        [TestMethod]
        public void AclWorkspaceTest()
        {
            NexusConfig config = new NexusConfig()
             {
                 LoginProfile = jUser.Create("MyUser", "Manager"),
             };
            using (ClientNexus nexus = ClientNexus.Create(config))
            {

                // Create a workspace
                jWorkspace mySpace = jWorkspace.Create(nexus, "MySpace");
                // Create some Jazz objects
                MyJazzClass one = new MyJazzClass(nexus, "One");
                MyJazzClass two = new MyJazzClass(nexus, "Two");
                // Add several objects to the workspace
                mySpace.Move(one);
                mySpace.Move(two);

                jRole manager = nexus.Cache.NamedObjects.Get<jRole>("Manager");
                // set 'mySpace' to be accessible only if the user posseses the role named 'Manager'.
                mySpace.Add(jAclItem.Accessible(manager));
                Assert.AreEqual(1, mySpace.ACL.Count());
                Assert.IsTrue(mySpace.IsAccessible);
                Assert.IsTrue(one.IsAccessible);
                Assert.IsTrue(two.IsAccessible);

                jUser guest = jUser.Create(nexus, "Guest");
                nexus.ChangeLoginProfile(guest);

                Assert.IsFalse(mySpace.IsAccessible);
                Assert.IsFalse(one.IsAccessible);
                Assert.IsFalse(two.IsAccessible);

                try
                {
                    string name = one.Name;
                    Assert.Fail();
                }
                catch(Exception ex)
                {
                    Assert.IsTrue(ex is AccessViolationException);
                }

            }

        }
        #endregion
        #region MySimpleJazzClass
        /// <summary>
        /// 
        /// </summary>
        [Jazz]
        public class MyJazzClass : jName
        {
            public MyJazzClass(ClientNexus nexus, string name)
                : base(nexus, name)
            {
            }
        }
        #endregion
        #region AclMyClassTest
        /// <summary>
        /// Demonstrates how to create a jObject instance that is only accessible given
        /// that the logged in user has a roled named "Manager".
        /// </summary>
        [TestMethod]
        public void AclMyClassTest()
        {
            NexusConfig config = new NexusConfig()
            {
                LoginProfile = jUser.Create("MyUser", "Manager"),
            };
            using (ClientNexus nexus = ClientNexus.Create(config))
            {

                // Create some Jazz objects
                MyAclJazzClass one = new MyAclJazzClass(nexus, "One");
                MyAclJazzClass two = new MyAclJazzClass(nexus, "Two");
                

                jRole manager = nexus.Cache.NamedObjects.Get<jRole>("Manager");
                // set 'one' to be accessible only if the user posseses the role named 'Manager'.
                one.Add(jAclItem.Accessible(manager));
                Assert.IsTrue(one.IsAccessible);
                Assert.IsTrue(two.IsAccessible);

                jUser guest = jUser.Create(nexus, "Guest");
                nexus.ChangeLoginProfile(guest);

                Assert.IsFalse(one.IsAccessible);
                Assert.IsTrue(two.IsAccessible);

                try
                {
                    string name = one.Name;
                    Assert.Fail();
                }
                catch (Exception ex)
                {
                    Assert.IsTrue(ex is AccessViolationException);
                }

            }

        }
        #endregion
        #region MyAclJazzClass
        /// <summary>
        /// This simple class has public methods that support
        /// setting and viewing the ACL.
        /// </summary>
        [Jazz]
        public class MyAclJazzClass : jName
        {
            public MyAclJazzClass(ClientNexus nexus, string name)
                : base(nexus, name)
            {
            }
            //
            // Clone and own this code.
            // Place it in a Jazz Class that
            // requires the ability to set and view the ACL via public methods.
            // More sophisticated ACL control can be achieved by using the
            // "Grant Construct" - http://wiki.jazzfire.net/grant.ashx
            #region ACL -Add/Remove
            /// <summary>
            /// Returns the ACL (Access Control List) for this jObject.  
            /// The ACL controls accessibility of this '<see cref="jObject"/>' instance
            /// based on the logged in user's roles.
            /// <para>Note: If the ACL sequence is empty then there are no access restrictions.</para>
            /// </summary>
            public IEnumerable<jAclItem> ACL
            {
                get { return base._ACL; }
            }
            /// <summary>
            /// Add a '<see cref="jAclItem"/>' to this jObject's ACL.
            /// </summary>
            /// <param name="item"></param>
            public void Add(jAclItem item)
            {
                base._Add(item);
            }
            /// <summary>
            /// Remove a '<see cref="jAclItem"/>' from this jObject's ACL.
            /// </summary>
            /// <param name="item"></param>
            public void Remove(jAclItem item)
            {
                base._Remove(item);
            }
            #endregion
        }
        #endregion
    }
}
